若依vue中字典执行过程浅析 | 您所在的位置:网站首页 › dictslsp 原理 › 若依vue中字典执行过程浅析 |
1.导入并使用插件DataDict
/**
* file:src/main.js
*/
// 字典数据组件
import DictData from '@/components/DictData'
DictData.install()
/**
*file:src/components/DictData/index.js
*/
import Vue from 'vue'
import DataDict from '@/utils/dict'
import { getDicts as getDicts } from '@/api/system/dict/data'
function install() {
Vue.use(DataDict, {
metas: {
'*': {
labelField: 'dictLabel',
valueField: 'dictValue',
request(dictMeta) { //注意这个
return getDicts(dictMeta.type).then(res => res.data)
},
},
},
})
}
export default {
install,
}
2. DataDict初始化字典数据 , 混入dict,传给监听器回调
//file:src/utils/dict/index.js
import Dict from './Dict'
import { mergeOptions } from './DictOptions'
export default function(Vue, options) {
mergeOptions(options)
Vue.mixin({
data() {
if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) {
return {}
}
const dict = new Dict()
dict.owner = this
return {
dict
}
},
created() {
if (!(this.dict instanceof Dict)) {
return
}
options.onCreated && options.onCreated(this.dict)
this.dict.init(this.$options.dicts).then(() => {
options.onReady && options.onReady(this.dict)
this.$nextTick(() => {
this.$emit('dictReady', this.dict)
if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) {
this.$options.methods.onDictReady.call(this, this.dict)
}
})
})
},
})
}
3. dict.init(this.$options.dicts) 给dict 赋值
import Vue from 'vue'
import { mergeRecursive } from "@/utils/rytech";
import DictMeta from './DictMeta'
import DictData from './DictData'
const DEFAULT_DICT_OPTIONS = {
types: [],
}
/**
* @classdesc 字典
* @property {Object} label 标签对象,内部属性名为字典类型名称
* @property {Object} dict 字段数组,内部属性名为字典类型名称
* @property {Array.} _dictMetas 字典元数据数组
*/
export default class Dict {
constructor() {
this.owner = null
this.label = {}
this.type = {}
}
init(options) {
if (options instanceof Array) {
options = { types: options }
}
const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options)
if (opts.types === undefined) {
throw new Error('need dict types')
}
const ps = []
this._dictMetas = opts.types.map(t => DictMeta.parse(t))
this._dictMetas.forEach(dictMeta => {
const type = dictMeta.type
Vue.set(this.label, type, {})
Vue.set(this.type, type, [])
if (dictMeta.lazy) {
return
}
ps.push(loadDict(this, dictMeta))
})
return Promise.all(ps)
}
/**
* 重新加载字典
* @param {String} type 字典类型
*/
reloadDict(type) {
const dictMeta = this._dictMetas.find(e => e.type === type)
if (dictMeta === undefined) {
return Promise.reject(`the dict meta of ${type} was not found`)
}
return loadDict(this, dictMeta)
}
}
/**
* 加载字典
* @param {Dict} dict 字典
* @param {DictMeta} dictMeta 字典元数据
* @returns {Promise}
*/
function loadDict(dict, dictMeta) {
return dictMeta.request(dictMeta)
.then(response => {
const type = dictMeta.type
let dicts = dictMeta.responseConverter(response, dictMeta)
if (!(dicts instanceof Array)) {
console.error('the return of responseConverter must be Array.')
dicts = []
} else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) {
console.error('the type of elements in dicts must be DictData')
dicts = []
}
dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts)
dicts.forEach(d => {
Vue.set(dict.label[type], d.value, d.label)
})
return dicts
})
}
先判断了是不是数组 我这里this.$options.dicts是字典类型的数组 然后给了opt.types 用 mergeRecursive 将opt.types合并到 DEFAULT_DICT_OPTIONS // 数据合并 export function mergeRecursive(source, target) { for (var p in target) { try { if (target[p].constructor == Object) { source[p] = mergeRecursive(source[p], target[p]); } else { source[p] = target[p]; } } catch(e) { source[p] = target[p]; } } return source; };执行了 this._dictMetas = opts.types.map(t => DictMeta.parse(t)) 然后loadDict(this, dictMeta) load中调用了dictMeta.request request(dictMeta) { return getDicts(dictMeta.type).then(res => res.data) }最后push到空数组ps中统一执行 4.DictMeta 字典元数据 /** * @classdesc 字典元数据 * @property {String} type 类型 * @property {Function} request 请求 * @property {String} label 标签字段 * @property {String} value 值字段 */ export default class DictMeta { constructor(options) { this.type = options.type this.request = options.request, this.responseConverter = options.responseConverter this.labelField = options.labelField this.valueField = options.valueField this.lazy = options.lazy === true } } /** * 解析字典元数据 * @param {Object} options * @returns {DictMeta} */ DictMeta.parse= function(options) { let opts = null if (typeof options === 'string') { opts = DictOptions.metas[options] || {} opts.type = options } else if (typeof options === 'object') { opts = options } opts = mergeRecursive(DictOptions.metas['*'], opts) return new DictMeta(opts) } 5.DictOptions DictMeta的配置项DictOptions是一个DictMeta的一个默认配置项 这里提供了默认的labelField等和一个请求函数和映射转换函数 要注意的是 labelField,valueField,request在上面已经被赋值了 如下 import { mergeRecursive } from "@/utils/rytech"; import dictConverter from './DictConverter' export const options = { metas: { '*': { /** * 字典请求,方法签名为function(dictMeta: DictMeta): Promise */ request: (dictMeta) => { console.log(`load dict ${dictMeta.type}`) return Promise.resolve([]) }, /** * 字典响应数据转换器,方法签名为function(response: Object, dictMeta: DictMeta): DictData */ responseConverter, labelField: 'label', valueField: 'value', }, }, /** * 默认标签字段 */ DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'], /** * 默认值字段 */ DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'], } /** * 映射字典 * @param {Object} response 字典数据 * @param {DictMeta} dictMeta 字典元数据 * @returns {DictData} */ function responseConverter(response, dictMeta) { const dicts = response.content instanceof Array ? response.content : response if (dicts === undefined) { console.warn(`no dict data of "${dictMeta.type}" found in the response`) return [] } return dicts.map(d => dictConverter(d, dictMeta)) } export function mergeOptions(src) { mergeRecursive(options, src) } export default options |
CopyRight 2018-2019 实验室设备网 版权所有 |